package jgcp.master.management;

import java.util.concurrent.PriorityBlockingQueue;

import jgcp.common.Task;
import jgcp.master.scheduler.EDF;
import jgcp.master.scheduler.EDF_CB;
import jgcp.master.scheduler.FCFS;
import jgcp.master.scheduler.ScheduleAlgorithm;

/**
 * 
 * @Date 29/05/2009
 * @author Jie Zhao (288654)
 * @version 1.0
 */
public class TaskQueue {
	private static TaskQueue instance = new TaskQueue();
	private final static int QUEUE_CAPACITY = 100;
	private PriorityBlockingQueue<Task> taskqueue = new PriorityBlockingQueue<Task>(
			QUEUE_CAPACITY, new FCFS());
	private ScheduleAlgorithm currentAlgorithm = ScheduleAlgorithm.FCFS;

	private TaskQueue() {
	}

	public static TaskQueue getInstance() {
		return instance;
	}

	public Task take() throws InterruptedException {
//		System.out.println("Taking task from queue...");
		return taskqueue.take();
	}

	public void put(Task t) {
//		System.out.println("Putting task "+t+" into queue.");
		taskqueue.put(t);
	}

	/**
	 * Change the scheduling algorithm
	 * 
	 * @param sa
	 */
	public synchronized void changeAlgorithm(ScheduleAlgorithm sa) {
		if (sa == currentAlgorithm)
			return;
		else {
			currentAlgorithm = sa;
			PriorityBlockingQueue<Task> newQueue;
			int initialSize = taskqueue.size() > QUEUE_CAPACITY ? taskqueue
					.size() : QUEUE_CAPACITY;
			switch (sa) {
			case FCFS:
				newQueue = new PriorityBlockingQueue<Task>(initialSize,
						new FCFS());
				break;
			case EDF:
				newQueue = new PriorityBlockingQueue<Task>(initialSize,
						new EDF());
				break;
			case EDF_CB:
				newQueue = new PriorityBlockingQueue<Task>(initialSize,
						new EDF_CB());
				break;
			default:
				newQueue = new PriorityBlockingQueue<Task>(initialSize,
						new FCFS());
				break;
			}
			taskqueue.drainTo(newQueue);
			taskqueue = newQueue;
		}
	}
}
